<template>
	<el-scrollbar height="100%">
		<div class="json_box">
			<module_container title="JSON转换:">
				<div class="json_editor">
					<div class="search">
						<el-input
							v-model="search_str"
							placeholder="查找"
							class="input-with-select"
							@keyup.enter.native="search_click">
							<template #append>
								<el-button
									@click="search_click"
									:icon="Search" />
							</template>
						</el-input>
						<el-tooltip
							effect="light"
							content="Ctrl+S: 查找上一个匹配项"
							placement="top"
							><div
								class="btn"
								@click="navigateToNextMatch(-1)">
								上一个
							</div></el-tooltip
						>
						<el-tooltip
							effect="light"
							content="Ctrl+D: 查找上一个匹配项"
							placement="top"
							><div
								class="btn"
								@click="navigateToNextMatch(1)">
								下一个
							</div></el-tooltip
						>
						<el-checkbox
							v-model="case_sensitive"
							label="区分大小写"
							border />
						<el-checkbox
							v-model="full_match"
							label="全字匹配"
							border />
					</div>
					<div class="row">
						<div class="json_left">
							<el-input
								v-model="json_data_str"
								type="textarea"
								placeholder="请输入JSON数据"
								resize="none"
								@change="json_data_change" />
						</div>
						<div class="json_right">
							<!-- <vue-json-pretty :data="json_data" /> -->
							<div
								ref="editor_container"
								class="monaco-editor-container"></div>
						</div>
					</div>
				</div>
			</module_container>
		</div>
	</el-scrollbar>
</template>
<script setup>
	import { ref, onMounted } from "vue";
	import module_container from "@/components/module_container/index.vue";
	import { Search } from "@element-plus/icons-vue";
	import * as monaco from "monaco-editor";
	import { my_message } from "@/utils/my_message/index.js";

	const msg = my_message();

	const json_data_str = ref("");
	const search_str = ref("");
	const editor_container = ref(null);
	let editor;
	const options = {
		value: "", // 使用格式化后的 JSON
		language: "json", // 设置为 JSON 语言模式
		// theme: "vs-dark",
		theme: "vs",
		automaticLayout: true,
		minimap: { enabled: true }, // 可选：启用缩略图
		scrollBeyondLastLine: false,
		fontSize: 14,
		lineNumbers: "on", // 显示行号
		roundedSelection: true,
		formatOnPaste: true, // 粘贴时自动格式化
		formatOnType: true, // 输入时自动格式化（可选）
		// 新增 readOnly 选项，设置为 true 禁止编辑
		readOnly: true, // 禁止编辑
		folding: true, // 启用折叠（0.20.0 默认已开启）
		foldingStrategy: "indentation", // 自动解析语法折叠
	};
	let currentMatchIndex = 0;
	// 是否区分大小写
	const case_sensitive = ref(false);
	// 是否全字匹配
	const full_match = ref(false);

	onMounted(() => {
		editor = monaco.editor.create(editor_container.value, options);
		// 绑定导航快捷键
		editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_D, () => {
			navigateToNextMatch(1);
		}); // F3
		editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, () => {
			navigateToNextMatch(-1);
		}); // Shift+F3
	});

	const search_click = () => {
		searchInEditor(editor, search_str.value);
	};
	const json_data_change = () => {
		if (!json_data_str.value) {
			editor.setValue("");
			return;
		}
		function trim_quotes(str) {
			if (str.startsWith('"') && str.endsWith('"')) {
				return str.slice(1, -1).replace(/\\/g, ""); // 去掉首尾字符
			}
			return str.replace(/\\/g, ""); // 否则返回原字符串
		}
		let data_str = trim_quotes(json_data_str.value);
		try {
			let data = JSON.parse(data_str);
			editor.setValue(JSON.stringify(data, null, 2)); // 解析成功，是合法 JSON
		} catch (e) {
			msg.msg_error("解析失败，不是合法 JSON"); // 解析失败，不是合法 JSON
		}
	};

	const searchInEditor = (editor, search_text) => {
		const model = editor.getModel();
		if (!model) return;

		// 清除之前的搜索结果
		if (window.currentSearchDecorations) {
			editor.deltaDecorations(window.currentSearchDecorations, []);
			window.currentSearchDecorations = null;
		}

		// 查找所有匹配项（支持正则表达式）
		const matches = model.findMatches(
			search_text,
			false, // 是否仅搜索当前选区（默认 false，搜索全文）
			false, // 是否启用正则表达式
			case_sensitive.value, // 是否区分大小写
			full_match.value ? editor.getOption(116) : null, // 是否启用单词边界匹配
			true // 是否返回捕获组
		);

		if (matches.length === 0) {
			msg.msg_warning("未找到匹配项");
			return;
		}

		// 高亮所有匹配项
		window.currentSearchDecorations = editor.deltaDecorations(
			[],
			matches.map(match => ({
				range: match.range,
				options: {
					className: "search-highlight", // 自定义 CSS 类
					stickiness:
						monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
				},
			}))
		);

		// 跳转到第一个匹配项
		editor.revealRangeInCenter(matches[0].range);
		editor.setSelection(matches[0].range);
	};

	const navigateToNextMatch = (direction = 1) => {
		if (!window.currentSearchDecorations) return;

		const model = editor.getModel();
		const decorations = model
			.getDecorationsInRange(model.getFullModelRange())
			.filter(d => d.options.className === "search-highlight");

		if (decorations.length === 0) return;

		currentMatchIndex =
			(currentMatchIndex + direction + decorations.length) % decorations.length;
		const range = decorations[currentMatchIndex].range;

		editor.revealRangeInCenter(range);
		editor.setSelection(range);
	};
</script>
<style lang="less" scoped>
	.json_box {
		width: 100%;
		height: 100%;
		padding: 15px;
		box-sizing: border-box;
		--height: 650px;

		.json_editor {
			width: 100%;
			height: 100%;

			.search {
				width: 100%;
				display: flex;
				align-items: center;
				.input-with-select {
					width: 300px;
				}
				.btn {
					margin-left: 20px;
				}
				.el-checkbox {
					margin: 0 0 0 20px;
				}
			}

			.row {
				display: flex;
				flex-wrap: nowrap;
				justify-content: space-between;
				height: var(--height);
				margin-top: 10px;

				.json_left {
					width: 49%;
					height: var(--height);
					box-sizing: border-box;

					:deep(.el-textarea__inner) {
						height: var(--height);
						border: var(--split-line);
						border-radius: 0 !important;
						box-shadow: none !important;
					}
				}

				.json_right {
					width: 49%;
					height: var(--height);
					box-sizing: border-box;
					overflow: hidden;
					border: var(--split-line);
					// padding: 5px 11px !important;

					.monaco-editor-container {
						// width: 100% !important;
						height: 100% !important;

						:deep(.search-highlight) {
							background-color: rgba(255, 255, 0, 1) !important;
							/* 黄色高亮 */
							border-radius: 2px;
						}
						// :deep(.monaco-editor .view-overlays .folding-marker) {
						//   display: block !important;
						// }
					}
				}
			}
		}
	}
</style>
